package cn.gwm.flink.streaming.function.process;

import cn.gwm.flink.streaming.beans.estimateSoh.ConfigData;
import cn.gwm.flink.streaming.beans.estimateSoh.EstimateSohRecord;
import cn.gwm.flink.streaming.beans.estimateSoh.EstimateSohRecordPhev;
import cn.gwm.utils.StreamUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
import org.apache.flink.streaming.api.windowing.windows.GlobalWindow;
import org.apache.flink.util.Collector;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * soh估算两条记录统计属性处理函数
 *
 * @author GW00283474
 */
public class EstimateSohCountPhevProcessFunction extends ProcessWindowFunction<EstimateSohRecordPhev, EstimateSohRecordPhev, String, GlobalWindow> {

    private static final Log log = LogFactory.get();
    /**
     * 数据舍弃判断：dVmax 或者dVmin小于等于 ？V
     */
    static String DATA_DISCARD_MAX ="dataDiscardMax";
    /**
     * 数据舍弃判断：dVmax 或者dVmin大于等于 ？V
     */
    static String DATA_DISCARD_MIN = "dataDiscardMin";
    @Override
    public void process(String s, ProcessWindowFunction<EstimateSohRecordPhev, EstimateSohRecordPhev, String, GlobalWindow>.Context context, Iterable<EstimateSohRecordPhev> elements, Collector<EstimateSohRecordPhev> collector) throws Exception {

       try {
           List<EstimateSohRecordPhev> collect = StreamUtil.convertIterator(elements.iterator()).collect(Collectors.toList());
           if(collect.size()>1){
               Iterator<EstimateSohRecordPhev> iterator = elements.iterator();
               EstimateSohRecordPhev last = iterator.next();
               EstimateSohRecordPhev current = iterator.next();
               //单体最大电压两次的差值(本次减上一次)
               BigDecimal dvMax = current.getBMS_CellMaxVolt().subtract(last.getBMS_CellMaxVolt()).setScale(2, BigDecimal.ROUND_HALF_UP);
               //单体最小电压两次的差值(本次减上一次)
               BigDecimal dvMin = current.getBMS_CellVoltMin().subtract(last.getBMS_CellVoltMin()).setScale(2, BigDecimal.ROUND_HALF_UP);
               current.setDvMax(dvMax);
               current.setDvMin(dvMin);

               //动力电池内部SOC最大值两次的差值(本次减上一次)
               BigDecimal differenceSocMax = current.getBMS_CellSOCMax().subtract(last.getBMS_CellSOCMax()).setScale(2, BigDecimal.ROUND_HALF_UP);
               //动力电池内部SOC最大值两次的差值(本次减上一次)
               BigDecimal differenceSocMin = current.getBMS_CellSOCMin().subtract(last.getBMS_CellSOCMin()).setScale(2, BigDecimal.ROUND_HALF_UP);
               current.setDifferenceSocMax(differenceSocMax);
               current.setDifferenceSocMin(differenceSocMin);

               //计算充放电容量差两次的差值(本次减上一次)
               BigDecimal dQ = current.getDQ().subtract(last.getDQ());
               current.setDQ(dQ);
               if (0 != dvMax.doubleValue()) {
                   //计算比值1(等于dQ除以dV_max)
                   current.setRatio1(dQ.divide(dvMax, 2, BigDecimal.ROUND_HALF_UP));
               }
               if (0 != dvMin.doubleValue()) {
                   //计算比值2(等于dQ除以dV_min)
                   current.setRatio2(dQ.divide(dvMin, 2, BigDecimal.ROUND_HALF_UP));
               }
               //检查神经网络模型舍弃条件
               checkAbandon(current);
               //检查容量法舍弃条件（一期需求暂时先给true）
               //checkCapacityAbandon(current);
               current.setCapacityAbandonFlag(true);
               collector.collect(current);
           }
       }catch (Exception e){
           System.out.println("---------------EstimateSohCountProcessFunction中存在异常");
           e.printStackTrace();
       }
    }

    /**
     * 检查神经网络模型舍弃条件
     * @param record
     */
    void checkAbandon(EstimateSohRecordPhev record) {
        if (BooleanUtil.or(null == record.getRatio1(), null == record.getRatio2())) {
            record.setNetModelAbandonFlag(true);
        }else{
            //比值1或比值2其一为正的舍弃
            boolean ratio1Flag= NumberUtil.isGreater(record.getRatio1(),new BigDecimal("0"));
            boolean ratio2Flag= NumberUtil.isGreater(record.getRatio2(),new BigDecimal("0"));
            if(BooleanUtil.or(ratio1Flag,ratio2Flag)){
                record.setNetModelAbandonFlag(true);
            }
            //dV_max或dV_min其一值在[-0,01,0.01]内的舍弃
            BigDecimal dataDiscardMax=new BigDecimal("0.01");
            ConfigData configData = record.getConfigDataMap().get(DATA_DISCARD_MAX);
            if(Objects.nonNull(configData)){
                dataDiscardMax=new BigDecimal(configData.getConfigValue());
            }
            BigDecimal dataDiscardMin=new BigDecimal("-0.01");
            ConfigData configDataMin = record.getConfigDataMap().get(DATA_DISCARD_MIN);
            if(Objects.nonNull(configDataMin)){
                dataDiscardMin=new BigDecimal(configDataMin.getConfigValue());
            }
            boolean dvMaxFlag=BooleanUtil.and(NumberUtil.isGreaterOrEqual(record.getDvMax(),dataDiscardMin),
                    NumberUtil.isLessOrEqual(record.getDvMax(),dataDiscardMax));
            boolean dvMinFlag=BooleanUtil.and(NumberUtil.isGreaterOrEqual(record.getDvMin(),dataDiscardMin),
                    NumberUtil.isLessOrEqual(record.getDvMin(),dataDiscardMax));
            if(BooleanUtil.or(dvMaxFlag,dvMinFlag)){
                record.setNetModelAbandonFlag(true);
            }

        }
    }

    /**
     * 检查容量法舍弃条件
     * @param record
     */
    void checkCapacityAbandon(EstimateSohRecordPhev record){
        boolean dqFlag=BooleanUtil.and(NumberUtil.isGreaterOrEqual(record.getDQ(),new BigDecimal("-10")),
                NumberUtil.isLessOrEqual(record.getDQ(),new BigDecimal("10")));
        //-10<=dQ<=10的舍弃
        if(dqFlag){
            record.setCapacityAbandonFlag(true);
        }
        //difference_soc_max或difference_soc_min其一值在[0.00,5.00]内的舍弃
        boolean diffSocMax=BooleanUtil.and(NumberUtil.isGreaterOrEqual(record.getDifferenceSocMax(),new BigDecimal("0.00")),
                NumberUtil.isLessOrEqual(record.getDifferenceSocMax(),new BigDecimal("5.00")));
        boolean diffSocMin=BooleanUtil.and(NumberUtil.isGreaterOrEqual(record.getDifferenceSocMin(),new BigDecimal("0.00")),
                NumberUtil.isLessOrEqual(record.getDifferenceSocMin(),new BigDecimal("5.00")));
        if(BooleanUtil.or(diffSocMax,diffSocMin)){
            record.setCapacityAbandonFlag(true);
        }
    }
}


